package com.yupi.springbootinit.statemachine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.statemachine.core.StateTransitionRecord;
import com.yupi.springbootinit.statemachine.dto.StateTransitionRecordQueryRequest;
import com.yupi.springbootinit.statemachine.mapper.StateTransitionRecordMapper;
import com.yupi.springbootinit.statemachine.permission.PermissionManager;
import com.yupi.springbootinit.statemachine.service.StateTransitionRecordService;
import com.yupi.springbootinit.statemachine.vo.StateTransitionStatisticsVO;
import com.yupi.springbootinit.utils.SqlUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 状态转换记录服务实现
 */
@Slf4j
@Service
public class StateTransitionRecordServiceImpl extends ServiceImpl<StateTransitionRecordMapper, StateTransitionRecord> 
        implements StateTransitionRecordService {
    
    @Resource
    private StateTransitionRecordMapper stateTransitionRecordMapper;
    
    @Resource
    private PermissionManager permissionManager;
    
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    @Override
    public IPage<StateTransitionRecord> queryRecords(StateTransitionRecordQueryRequest request) {
        QueryWrapper<StateTransitionRecord> queryWrapper = buildQueryWrapper(request);
        
        // 分页查询
        Page<StateTransitionRecord> page = new Page<>(request.getCurrent(), request.getPageSize());
        
        // 排序
        if (StringUtils.hasText(request.getSortField())) {
            boolean isAsc = "asc".equalsIgnoreCase(request.getSortOrder());
            if (SqlUtils.validSortField(request.getSortField())) {
                queryWrapper.orderBy(true, isAsc, request.getSortField());
            }
        } else {
            // 默认按创建时间倒序
            queryWrapper.orderByDesc("create_time");
        }
        
        IPage<StateTransitionRecord> result = this.page(page, queryWrapper);
        
        log.debug("查询状态转换记录: 实体类型={}, 结果数={}", request.getEntityType(), result.getRecords().size());
        
        return result;
    }
    
    @Override
    public List<StateTransitionRecord> getEntityTransitionHistory(String entityType, Long entityId) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entity_type", entityType)
                   .eq("entity_id", entityId)
                   .orderByAsc("create_time");
        
        List<StateTransitionRecord> records = this.list(queryWrapper);
        
        log.debug("查询实体状态转换历史: 实体[{}:{}], 记录数: {}", entityType, entityId, records.size());
        
        return records;
    }
    
    @Override
    public IPage<StateTransitionRecord> queryRecordsWithPermission(StateTransitionRecordQueryRequest request, Long userId) {
        // 先查询记录
        IPage<StateTransitionRecord> page = queryRecords(request);
        
        // 过滤用户有权限查看的记录
        List<StateTransitionRecord> filteredRecords = page.getRecords().stream()
                .filter(record -> hasPermissionToViewRecord(userId, record))
                .collect(Collectors.toList());
        
        // 重新设置记录
        page.setRecords(filteredRecords);
        
        log.debug("权限过滤后的记录数: 用户ID={}, 原始数={}, 过滤后数={}", 
                userId, page.getTotal(), filteredRecords.size());
        
        return page;
    }
    
    @Override
    public StateTransitionStatisticsVO getTransitionStatistics(String entityType, String startTime, String endTime) {
        StateTransitionStatisticsVO statistics = new StateTransitionStatisticsVO();
        statistics.setEntityType(entityType);
        statistics.setStartTime(startTime);
        statistics.setEndTime(endTime);
        
        // 构建基础查询条件
        QueryWrapper<StateTransitionRecord> baseQuery = new QueryWrapper<>();
        if (StringUtils.hasText(entityType)) {
            baseQuery.eq("entity_type", entityType);
        }
        if (StringUtils.hasText(startTime)) {
            baseQuery.ge("create_time", startTime);
        }
        if (StringUtils.hasText(endTime)) {
            baseQuery.le("create_time", endTime);
        }
        
        // 基础统计
        List<StateTransitionRecord> allRecords = this.list(baseQuery);
        long totalTransitions = allRecords.size();
        long successTransitions = allRecords.stream()
                .filter(r -> r.getSuccess() != null)
                .mapToLong(r -> Boolean.TRUE.equals(r.getSuccess()) ? 1L : 0L)
                .sum();
        long failedTransitions = totalTransitions - successTransitions;
        
        statistics.setTotalTransitions(totalTransitions);
        statistics.setSuccessTransitions(successTransitions);
        statistics.setFailedTransitions(failedTransitions);
        
        // 修复：使用BigDecimal.valueOf()
        if (totalTransitions > 0) {
            statistics.setSuccessRate(BigDecimal.valueOf(successTransitions * 100.0 / totalTransitions)
                    .setScale(2, RoundingMode.HALF_UP));
        } else {
            statistics.setSuccessRate(BigDecimal.ZERO);
        }
        
        // 耗时统计
        OptionalDouble avgDurationOpt = allRecords.stream()
                .filter(r -> r.getDuration() != null)
                .mapToLong(StateTransitionRecord::getDuration)
                .average();
        
        statistics.setAvgDuration(avgDurationOpt.isPresent() ? (long) avgDurationOpt.getAsDouble() : 0L);
        statistics.setMaxDuration(allRecords.stream()
                .filter(r -> r.getDuration() != null)
                .mapToLong(StateTransitionRecord::getDuration)
                .max().orElse(0L));
        statistics.setMinDuration(allRecords.stream()
                .filter(r -> r.getDuration() != null)
                .mapToLong(StateTransitionRecord::getDuration)
                .min().orElse(0L));
        
        // 慢转换统计(>5秒)
        long slowTransitions = allRecords.stream()
                .filter(r -> r.getDuration() != null && r.getDuration() > 5000)
                .count();
        statistics.setSlowTransitions(slowTransitions);
        
        if (totalTransitions > 0) {
            statistics.setSlowTransitionRate(BigDecimal.valueOf(slowTransitions * 100.0 / totalTransitions)
                    .setScale(2, RoundingMode.HALF_UP));
        } else {
            statistics.setSlowTransitionRate(BigDecimal.ZERO);
        }
        
        // 按转换类型统计
        statistics.setTransitionTypeStats(buildTransitionTypeStats(allRecords));
        
        // 按操作人统计
        statistics.setOperatorStats(buildOperatorStats(allRecords));
        
        // 按小时统计
        statistics.setHourlyStats(buildHourlyStats(allRecords));
        
        // 按日期统计
        statistics.setDailyStats(buildDailyStats(allRecords));
        
        // 错误统计
        statistics.setErrorStats(buildErrorStats(allRecords));
        
        log.debug("生成状态转换统计: 实体类型={}, 总记录数={}", entityType, totalTransitions);
        
        return statistics;
    }
    
    @Override
    public List<Map<String, Object>> getTransitionFrequencyStats(String entityType, String startTime, String endTime) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("from_state_code", "to_state_code", "COUNT(*) as frequency")
                   .groupBy("from_state_code", "to_state_code")
                   .orderByDesc("frequency");
        
        if (StringUtils.hasText(entityType)) {
            queryWrapper.eq("entity_type", entityType);
        }
        if (StringUtils.hasText(startTime)) {
            queryWrapper.ge("create_time", startTime);
        }
        if (StringUtils.hasText(endTime)) {
            queryWrapper.le("create_time", endTime);
        }
        
        return this.listMaps(queryWrapper);
    }
    
    @Override
    public List<Map<String, Object>> getTransitionDurationAnalysis(String entityType, String startTime, String endTime) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("from_state_code", "to_state_code", 
                           "AVG(duration) as avg_duration", 
                           "MAX(duration) as max_duration", 
                           "MIN(duration) as min_duration",
                           "COUNT(*) as count")
                   .isNotNull("duration")
                   .groupBy("from_state_code", "to_state_code")
                   .orderByDesc("avg_duration");
        
        if (StringUtils.hasText(entityType)) {
            queryWrapper.eq("entity_type", entityType);
        }
        if (StringUtils.hasText(startTime)) {
            queryWrapper.ge("create_time", startTime);
        }
        if (StringUtils.hasText(endTime)) {
            queryWrapper.le("create_time", endTime);
        }
        
        return this.listMaps(queryWrapper);
    }
    
    @Override
    public List<StateTransitionRecord> getFailedTransitions(String entityType, String startTime, String endTime, Integer limit) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("success", false)
                   .orderByDesc("create_time");
        
        if (StringUtils.hasText(entityType)) {
            queryWrapper.eq("entity_type", entityType);
        }
        if (StringUtils.hasText(startTime)) {
            queryWrapper.ge("create_time", startTime);
        }
        if (StringUtils.hasText(endTime)) {
            queryWrapper.le("create_time", endTime);
        }
        if (limit != null && limit > 0) {
            queryWrapper.last("LIMIT " + limit);
        }
        
        return this.list(queryWrapper);
    }
    
    @Override
    public List<Map<String, Object>> getOperatorTransitionStats(String startTime, String endTime) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("operator_id", "operator_name", 
                           "COUNT(*) as total_count",
                           "SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as success_count")
                   .isNotNull("operator_id")
                   .groupBy("operator_id", "operator_name")
                   .orderByDesc("total_count");
        
        if (StringUtils.hasText(startTime)) {
            queryWrapper.ge("create_time", startTime);
        }
        if (StringUtils.hasText(endTime)) {
            queryWrapper.le("create_time", endTime);
        }
        
        return this.listMaps(queryWrapper);
    }
    
    @Override
    public List<StateTransitionRecord> getSlowTransitions(Long thresholdMs, Integer limit) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("duration", thresholdMs)
                   .orderByDesc("duration");
        
        if (limit != null && limit > 0) {
            queryWrapper.last("LIMIT " + limit);
        }
        
        return this.list(queryWrapper);
    }
    
    @Override
    public List<StateTransitionRecord> exportRecords(StateTransitionRecordQueryRequest request, Long userId) {
        // 构建查询条件
        QueryWrapper<StateTransitionRecord> queryWrapper = buildQueryWrapper(request);
        
        // 排序
        if (StringUtils.hasText(request.getSortField())) {
            boolean isAsc = "asc".equalsIgnoreCase(request.getSortOrder());
            if (SqlUtils.validSortField(request.getSortField())) {
                queryWrapper.orderBy(true, isAsc, request.getSortField());
            }
        } else {
            queryWrapper.orderByDesc("create_time");
        }
        
        // 查询所有记录
        List<StateTransitionRecord> allRecords = this.list(queryWrapper);
        
        // 权限过滤
        List<StateTransitionRecord> filteredRecords = allRecords.stream()
                .filter(record -> hasPermissionToViewRecord(userId, record))
                .collect(Collectors.toList());
        
        log.info("导出状态转换记录: 用户ID={}, 总记录数={}, 权限过滤后={}", 
                userId, allRecords.size(), filteredRecords.size());
        
        return filteredRecords;
    }
    
    @Override
    public List<StateTransitionRecord> getEntityTransitionChain(String entityType, Long entityId) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entity_type", entityType)
                   .eq("entity_id", entityId)
                   .eq("success", true)
                   .orderByAsc("create_time");
        
        List<StateTransitionRecord> chain = this.list(queryWrapper);
        
        log.debug("查询实体状态转换链路: 实体[{}:{}], 链路长度: {}", entityType, entityId, chain.size());
        
        return chain;
    }
    
    @Override
    public boolean hasPermissionToViewRecord(Long userId, StateTransitionRecord record) {
        if (userId == null || record == null) {
            return false;
        }
        
        // 修复：使用正确的方法签名
        return permissionManager.canViewEntity(userId, record.getEntityType(), record.getEntityId());
    }
    
    /**
     * 构建查询条件
     */
    private QueryWrapper<StateTransitionRecord> buildQueryWrapper(StateTransitionRecordQueryRequest request) {
        QueryWrapper<StateTransitionRecord> queryWrapper = new QueryWrapper<>();
        
        if (request.getEntityId() != null) {
            queryWrapper.eq("entity_id", request.getEntityId());
        }
        
        if (StringUtils.hasText(request.getEntityType())) {
            queryWrapper.eq("entity_type", request.getEntityType());
        }
        
        if (!CollectionUtils.isEmpty(request.getEntityTypes())) {
            queryWrapper.in("entity_type", request.getEntityTypes());
        }
        
        if (StringUtils.hasText(request.getFromStateCode())) {
            queryWrapper.eq("from_state_code", request.getFromStateCode());
        }
        
        if (StringUtils.hasText(request.getToStateCode())) {
            queryWrapper.eq("to_state_code", request.getToStateCode());
        }
        
        // 修复：使用正确的字段名
        if (StringUtils.hasText(request.getFromState())) {
            queryWrapper.eq("from_state_code", request.getFromState());
        }
        
        if (StringUtils.hasText(request.getToState())) {
            queryWrapper.eq("to_state_code", request.getToState());
        }
        
        if (StringUtils.hasText(request.getEvent())) {
            queryWrapper.eq("event_code", request.getEvent());
        }
        
        if (StringUtils.hasText(request.getTransitionType())) {
            String[] parts = request.getTransitionType().split("->");
            if (parts.length == 2) {
                queryWrapper.eq("from_state_code", parts[0].trim())
                           .eq("to_state_code", parts[1].trim());
            }
        }
        
        if (request.getOperatorId() != null) {
            queryWrapper.eq("operator_id", request.getOperatorId());
        }
        
        if (StringUtils.hasText(request.getOperatorName())) {
            queryWrapper.like("operator_name", request.getOperatorName());
        }
        
        if (request.getSuccess() != null) {
            queryWrapper.eq("success", request.getSuccess());
        }
        
        if (StringUtils.hasText(request.getErrorCode())) {
            queryWrapper.eq("error_code", request.getErrorCode());
        }
        
        // 修复：使用正确的字段名
        if (StringUtils.hasText(request.getErrorMessage())) {
            queryWrapper.like("error_message", request.getErrorMessage());
        }
        
        if (StringUtils.hasText(request.getStartTime())) {
            queryWrapper.ge("create_time", request.getStartTime());
        }
        
        if (StringUtils.hasText(request.getEndTime())) {
            queryWrapper.le("create_time", request.getEndTime());
        }
        
        if (request.getMinDuration() != null) {
            queryWrapper.ge("duration", request.getMinDuration());
        }
        
        if (request.getMaxDuration() != null) {
            queryWrapper.le("duration", request.getMaxDuration());
        }
        
        if (StringUtils.hasText(request.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                    .like("remark", request.getKeyword())
                    .or()
                    .like("error_message", request.getKeyword()));
        }
        
        if (Boolean.TRUE.equals(request.getOnlyFailed())) {
            queryWrapper.eq("success", false);
        }
        
        if (Boolean.TRUE.equals(request.getOnlySlow())) {
            Long threshold = request.getSlowThreshold() != null ? request.getSlowThreshold() : 5000L;
            queryWrapper.gt("duration", threshold);
        }
        
        return queryWrapper;
    }
    
    /**
     * 构建转换类型统计
     */
    private List<StateTransitionStatisticsVO.TransitionTypeStatistics> buildTransitionTypeStats(List<StateTransitionRecord> records) {
        Map<String, List<StateTransitionRecord>> groupedByType = records.stream()
                .collect(Collectors.groupingBy(r -> r.getFromStateCode() + "->" + r.getToStateCode()));
        
        return groupedByType.entrySet().stream()
                .map(entry -> {
                    String transitionType = entry.getKey();
                    List<StateTransitionRecord> typeRecords = entry.getValue();
                    
                    StateTransitionStatisticsVO.TransitionTypeStatistics stat = 
                            new StateTransitionStatisticsVO.TransitionTypeStatistics();
                    stat.setTransitionType(transitionType);
                    stat.setCount((long) typeRecords.size());
                    
                    long successCount = typeRecords.stream()
                            .filter(r -> r.getSuccess() != null)
                            .mapToLong(r -> Boolean.TRUE.equals(r.getSuccess()) ? 1L : 0L)
                            .sum();
                    stat.setSuccessCount(successCount);
                    
                    if (typeRecords.size() > 0) {
                        stat.setSuccessRate(BigDecimal.valueOf(successCount * 100.0 / typeRecords.size())
                                .setScale(2, RoundingMode.HALF_UP));
                    } else {
                        stat.setSuccessRate(BigDecimal.ZERO);
                    }
                    
                    OptionalDouble avgDuration = typeRecords.stream()
                            .filter(r -> r.getDuration() != null)
                            .mapToLong(StateTransitionRecord::getDuration)
                            .average();
                    stat.setAvgDuration(avgDuration.isPresent() ? (long) avgDuration.getAsDouble() : 0L);
                    
                    return stat;
                })
                .sorted((a, b) -> Long.compare(b.getCount(), a.getCount()))
                .collect(Collectors.toList());
    }
    
    /**
     * 构建操作人统计
     */
    private List<StateTransitionStatisticsVO.OperatorStatistics> buildOperatorStats(List<StateTransitionRecord> records) {
        Map<Long, List<StateTransitionRecord>> groupedByOperator = records.stream()
                .filter(r -> r.getOperatorId() != null)
                .collect(Collectors.groupingBy(StateTransitionRecord::getOperatorId));
        
        return groupedByOperator.entrySet().stream()
                .map(entry -> {
                    Long operatorId = entry.getKey();
                    List<StateTransitionRecord> operatorRecords = entry.getValue();
                    
                    StateTransitionStatisticsVO.OperatorStatistics stat = 
                            new StateTransitionStatisticsVO.OperatorStatistics();
                    stat.setOperatorId(operatorId);
                    stat.setOperatorName(operatorRecords.get(0).getOperatorName());
                    stat.setCount((long) operatorRecords.size());
                    
                    long successCount = operatorRecords.stream()
                            .filter(r -> r.getSuccess() != null)
                            .mapToLong(r -> Boolean.TRUE.equals(r.getSuccess()) ? 1L : 0L)
                            .sum();
                    stat.setSuccessCount(successCount);
                    
                    if (operatorRecords.size() > 0) {
                        stat.setSuccessRate(BigDecimal.valueOf(successCount * 100.0 / operatorRecords.size())
                                .setScale(2, RoundingMode.HALF_UP));
                    } else {
                        stat.setSuccessRate(BigDecimal.ZERO);
                    }
                    
                    return stat;
                })
                .sorted((a, b) -> Long.compare(b.getCount(), a.getCount()))
                .collect(Collectors.toList());
    }
    
    /**
     * 构建小时统计
     */
    private List<StateTransitionStatisticsVO.HourlyStatistics> buildHourlyStats(List<StateTransitionRecord> records) {
        Map<Integer, List<StateTransitionRecord>> groupedByHour = records.stream()
                .filter(r -> r.getCreateTime() != null)
                .collect(Collectors.groupingBy(r -> {
                    // 将Date转换为LocalDateTime获取小时
                    return r.getCreateTime().toInstant()
                            .atZone(java.time.ZoneId.systemDefault())
                            .toLocalDateTime()
                            .getHour();
                }));
        
        return groupedByHour.entrySet().stream()
                .map(entry -> {
                    Integer hour = entry.getKey();
                    List<StateTransitionRecord> hourRecords = entry.getValue();
                    
                    StateTransitionStatisticsVO.HourlyStatistics stat = 
                            new StateTransitionStatisticsVO.HourlyStatistics();
                    stat.setHour(hour);
                    stat.setCount((long) hourRecords.size());
                    
                    long successCount = hourRecords.stream()
                            .filter(r -> r.getSuccess() != null)
                            .mapToLong(r -> Boolean.TRUE.equals(r.getSuccess()) ? 1L : 0L)
                            .sum();
                    stat.setSuccessCount(successCount);
                    
                    return stat;
                })
                .sorted(Comparator.comparing(StateTransitionStatisticsVO.HourlyStatistics::getHour))
                .collect(Collectors.toList());
    }
    
    /**
     * 构建日期统计
     */
    private List<StateTransitionStatisticsVO.DailyStatistics> buildDailyStats(List<StateTransitionRecord> records) {
        Map<String, List<StateTransitionRecord>> groupedByDate = records.stream()
                .filter(r -> r.getCreateTime() != null)
                .collect(Collectors.groupingBy(r -> {
                    // 将Date转换为LocalDate获取日期字符串
                    return r.getCreateTime().toInstant()
                            .atZone(java.time.ZoneId.systemDefault())
                            .toLocalDate()
                            .toString();
                }));
        
        return groupedByDate.entrySet().stream()
                .map(entry -> {
                    String date = entry.getKey();
                    List<StateTransitionRecord> dateRecords = entry.getValue();
                    
                    StateTransitionStatisticsVO.DailyStatistics stat = 
                            new StateTransitionStatisticsVO.DailyStatistics();
                    stat.setDate(date);
                    stat.setCount((long) dateRecords.size());
                    
                    long successCount = dateRecords.stream()
                            .filter(r -> r.getSuccess() != null)
                            .mapToLong(r -> Boolean.TRUE.equals(r.getSuccess()) ? 1L : 0L)
                            .sum();
                    stat.setSuccessCount(successCount);
                    
                    // 移除setAvgDuration调用，因为DailyStatistics中没有这个方法
                    
                    return stat;
                })
                .sorted(Comparator.comparing(StateTransitionStatisticsVO.DailyStatistics::getDate))
                .collect(Collectors.toList());
    }
    
    /**
     * 构建错误统计
     */
    private List<StateTransitionStatisticsVO.ErrorStatistics> buildErrorStats(List<StateTransitionRecord> records) {
        Map<String, List<StateTransitionRecord>> groupedByError = records.stream()
                .filter(r -> !Boolean.TRUE.equals(r.getSuccess()) && StringUtils.hasText(r.getErrorCode()))
                .collect(Collectors.groupingBy(StateTransitionRecord::getErrorCode));
        
        return groupedByError.entrySet().stream()
                .map(entry -> {
                    String errorCode = entry.getKey();
                    List<StateTransitionRecord> errorRecords = entry.getValue();
                    
                    StateTransitionStatisticsVO.ErrorStatistics stat = 
                            new StateTransitionStatisticsVO.ErrorStatistics();
                    stat.setErrorCode(errorCode);
                    stat.setCount((long) errorRecords.size());
                    
                    if (records.size() > 0) {
                        stat.setErrorRate(BigDecimal.valueOf(errorRecords.size() * 100.0 / records.size())
                                .setScale(2, RoundingMode.HALF_UP));
                    } else {
                        stat.setErrorRate(BigDecimal.ZERO);
                    }
                    
                    // 获取最近错误时间
                    Optional<StateTransitionRecord> latestError = errorRecords.stream()
                            .max(Comparator.comparing(StateTransitionRecord::getCreateTime));
                    if (latestError.isPresent()) {
                        stat.setLastErrorTime(latestError.get().getCreateTime().toString());
                    }
                    
                    return stat;
                })
                .sorted((a, b) -> Long.compare(b.getCount(), a.getCount()))
                .collect(Collectors.toList());
    }
}